/*
 * DynamicListSerializer.h
 *
 *  Created on: Oct 24, 2012
 *      Author: m
 */

#ifndef DYNAMICLISTSERIALIZER_H_
#define DYNAMICLISTSERIALIZER_H_

#include "DynamicSerializer.h"

namespace physical
{

/**
 * Serializador de listas dinámicas
 *
 * @deprecated DEPRECATED! Esta clase es obsoleta, solo se
 *              deja por compatibilidad, porque el árbol la
 *              utiliza.
 *
 * TODO: Refactorizar esta clase y mergearla con los otros
 *        serializadores
 */
template<typename T>
class DynamicListSerializer :
    public DynamicSerializer< std::list< typename DynamicSerializer<T>::_T_ptr > >
{
protected:
    typedef typename DynamicSerializer<T>::_T_ptr _ELEM_ptr;
    typedef typename std::list< _ELEM_ptr > _T_List;
    typedef typename DynamicSerializer< _T_List >::_T_ptr _T_List_ptr;

public:
    typedef typename std::shared_ptr< DynamicSerializer<T> > _T_Serializer_ptr;

protected:
    typedef unsigned long listSize_t;
    _T_Serializer_ptr m_recordSerializer;

public:

    DynamicListSerializer( _T_Serializer_ptr &serializer ) :
        m_recordSerializer( serializer )
    {
    }

    virtual ~DynamicListSerializer()
    {
    }

    size_t serialize( const _T_List &element, byteStream block )
    {
        typename _T_List::const_iterator it;
        byte* blockPtr;
        size_t bytesCount;
        size_t serializedBytes;
        listSize_t recordsCount;

        // Inizializo el puntero de serialización
        blockPtr = block;

        // Primero guardo la cantidad de registros que tiene la lista
        recordsCount = element.size();
        memcpy( blockPtr, &recordsCount, sizeof(listSize_t) );
        bytesCount = sizeof(listSize_t);
        blockPtr += bytesCount;

        // Luego voy serializando 1 a 1 los registros de la lista
        for ( it = element.begin(); it != element.end(); it++ )
        {
            serializedBytes = m_recordSerializer->serialize( *it, blockPtr );

            blockPtr += serializedBytes;
            bytesCount += serializedBytes;
        }

        return bytesCount;
    }

    size_t deserialize( const byteStream block, _T_List &element )
    {
        listSize_t recordsCount;
        size_t bytesDeserialized;
        byte* blockPtr;
        size_t bytesCount;
        _ELEM_ptr record;

        // Creo una nueva lista vacia
        element.clear();

        // Parseo la cantidad de registros a deserializar
        memcpy( &recordsCount, block, sizeof(listSize_t) );
        blockPtr = (byte*)block + sizeof(listSize_t);
        bytesCount = sizeof(listSize_t);

        // Deserializo cada registro y lo inserto en la lista
        for ( listSize_t i = 0; i < recordsCount; ++i )
        {
            bytesDeserialized = m_recordSerializer->deserialize( blockPtr, record );
            element.push_back( record );

            bytesCount += bytesDeserialized;
            blockPtr += bytesDeserialized;
        }

        return bytesCount;
    }


    size_t getSize( const _T_List &element )
    {
        typename _T_List::const_iterator it;
        size_t bytesCount;

        // Sumo los bytes para serializar la longitud de la lista
        bytesCount = sizeof( listSize_t );

        // Luego recorro la lista y acumulo la cant. de bytes para serializar cada registro
        for ( it = element.begin(); it != element.end(); it++ )
            bytesCount += m_recordSerializer->getSize( *it );

        return bytesCount;
    }

    size_t serialize( const _T_List_ptr &elementPtr, byteStream block )
    {
        return this->serialize( *elementPtr, block );
    }

    size_t deserialize( const byteStream block, _T_List_ptr &elementPtr )
    {
        elementPtr.reset( new _T_List );
        return this->deserialize( block, *elementPtr );
    }

    size_t getSize( const _T_List_ptr &elementPtr )
    {
        return this->getSize( *elementPtr );
    }

};

} /* namespace physical */
#endif /* DYNAMICLISTSERIALIZER_H_ */
